/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : DevKey.c
 * Author        : joki.zhu
 * Date          : 2019-10-18
 *
 * Record        :
 * 1.Date        : 2019-10-18
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include "app_common.h"
#include "hi_uartmsg.h"
#include "DevKey.h"
#include "Audio.h"
#include "hi_hal_syslink.h"

#define KEY_EVENT_NUM       (5)
#define KEY_EVENT_LOCK()    pthread_mutex_lock(&g_tKeyEventMutex);
#define KEY_EVENT_UNLOCK()  pthread_mutex_unlock(&g_tKeyEventMutex);

typedef struct {
    int bRun;
    KEY_TYPE_E enKeyType;
    KEY_STATE_E enKeyState;
    KEY_PROC_CALLBACK_FN_PTR pfnKeyProc;	
}KEV_EVENT_S;

typedef struct {
    KEY_TYPE_E enKeyType;
    KEY_STATE_E enKeyState;
    sem_t readSem;
    sem_t writeSem;
}KEY_MSG_S;

static KEV_EVENT_S g_stKeyEvent[KEY_EVENT_NUM];
static KEY_MSG_S g_stKeyMsg;
static pthread_t g_keyProcPid;
static pthread_mutex_t g_tKeyEventMutex = PTHREAD_MUTEX_INITIALIZER;

static void RecvKeyEventFromUart(HI_UARTMSG_PARM_S *pRcvMsg)
{
    if (HI_UARTMSG_M2S_KEYEVENT == pRcvMsg->u32MsgId)
    {
        sem_wait(&g_stKeyMsg.writeSem);     
#if 0
        int i = 0;
        printf("Data: ");
        for (i = 0; i < pRcvMsg->dataLen; i++)
        {
            printf("0x%x ", pRcvMsg->data[i]);
        }
        printf("\n");
#endif
        if (pRcvMsg->data[0] == 0x1)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_BELL;
        }
        else if (pRcvMsg->data[0] == 0x2)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_PICK;
            //AudioGetOpsHandle()->play_file_start(AUDIO_ALARM, AUDIO_TYPE_MP3, 0);
        }
        else if (pRcvMsg->data[0] == 0x3)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_CONFIG;
        }

        if (pRcvMsg->data[2] == 0x1) {
            g_stKeyMsg.enKeyState = KEY_STATE_LONGRESS;
        } else {
            g_stKeyMsg.enKeyState = KEY_STATE_PRESSED;
        }      

        sem_post(&g_stKeyMsg.readSem);
    }
}


static void RecvKeyEventFromWifi(HI_SYSLINK_PARM_S stRcvMsg)
{
    if (HI_SYSLINK_MSGID_W2S_KEY_EVENT == stRcvMsg.u32MsgId)
    {
        sem_wait(&g_stKeyMsg.writeSem);     
#if 0
        int i = 0;
        printf("Data: ");
        for (i = 0; i < pRcvMsg->dataLen; i++)
        {
            printf("0x%x ", pRcvMsg->data[i]);
        }
        printf("\n");
#endif
        if (stRcvMsg.data[0] == 0x0)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_BELL;
        }
        else if (stRcvMsg.data[0] == 0x1)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_PICK;
            //AudioGetOpsHandle()->play_file_start(AUDIO_ALARM, AUDIO_TYPE_MP3, 0);
        }
        else if (stRcvMsg.data[0] == 0x2)
        {
            g_stKeyMsg.enKeyType = KEY_TYPE_CONFIG;
        }

        if (stRcvMsg.data[1] == 0x1) {
            g_stKeyMsg.enKeyState = KEY_STATE_LONGRESS;
        } else {
            g_stKeyMsg.enKeyState = KEY_STATE_PRESSED;
        }      

        sem_post(&g_stKeyMsg.readSem);
    }
}

void *tskKeyRun(void *args)
{
    SET_THREAD_NAME("tskKeyRun");
    pthread_detach(pthread_self());

    KEV_EVENT_S *pstKeyEvent = (KEV_EVENT_S *)args;

    if (pstKeyEvent->pfnKeyProc != NULL)
    {
        pstKeyEvent->pfnKeyProc();
        pstKeyEvent->bRun = 0;
    }
    
    pthread_exit(0);
}

static int OnKeyEvent(KEY_TYPE_E enKeyType, KEY_STATE_E enKeyState)
{
    int index = 0;

    KEY_EVENT_LOCK();
    for (index = 0; index < KEY_EVENT_NUM; index++)
    {
        if (enKeyType == g_stKeyEvent[index].enKeyType &&
            enKeyState == g_stKeyEvent[index].enKeyState &&
            NULL != g_stKeyEvent[index].pfnKeyProc &&
            0 == g_stKeyEvent[index].bRun)
        {
            g_stKeyEvent[index].bRun = 1;
            pthread_t pid;
            int ret = pthread_create(&pid, NULL, (void *)tskKeyRun, (void *)(&g_stKeyEvent[index]));
            if (ret != 0) {
                LOGE("pthread_create tskKeyRun failed\n");
                g_stKeyEvent[index].bRun = 0;
                KEY_EVENT_UNLOCK();
                return ret;
            }
            
            break;
        }
    }
    KEY_EVENT_UNLOCK();

    return 0;
}

void *tskKeyProc(void *args)
{
    SET_THREAD_NAME("tskKeyProc");
    pthread_detach(pthread_self());
    
    while (1)
    {
        sem_wait(&g_stKeyMsg.readSem);
        OnKeyEvent(g_stKeyMsg.enKeyType, g_stKeyMsg.enKeyState);
        sem_post(&g_stKeyMsg.writeSem);
        LOGD("OnKeyEvent\n");
    }

    pthread_exit(0);
}

int KeyInit(void)
{
    int i = 0;
    int ret = -1;

    sem_init(&g_stKeyMsg.readSem, 0, 0);
    sem_init(&g_stKeyMsg.writeSem, 0, 1);
    g_stKeyMsg.enKeyType = KEY_TYPE_NONE;
    g_stKeyMsg.enKeyState = KEY_STATE_NONE;

    
    for (i = 0; i < KEY_EVENT_NUM; i++)
    {
        g_stKeyEvent[i].bRun = 0;
        g_stKeyEvent[i].enKeyType = KEY_TYPE_NONE;
        g_stKeyEvent[i].enKeyState = KEY_STATE_NONE;
        g_stKeyEvent[i].pfnKeyProc = NULL;
    }

    /* register recv key event from uart */
//    HI_UARTMSG_RegRecvCbk(RecvKeyEventFromUart);
    HI_HAL_SYSLINK_Register(RecvKeyEventFromWifi);
    
    ret = pthread_create(&g_keyProcPid, 0, (void *)tskKeyProc, NULL);
    if (ret != 0) {
        LOGE("pthread_create tskKeyProc failed\n");
        return ret;
    }
    
    return ret;
}

int KeyEventRegister(KEY_TYPE_E enKeyType, KEY_STATE_E enKeyState, KEY_PROC_CALLBACK_FN_PTR pfnKeyProc)
{
    int index = 0;

    for (index = 0; index < KEY_EVENT_NUM; index++)
    {
        if (NULL == g_stKeyEvent[index].pfnKeyProc) {
            break;
        } else if (pfnKeyProc == g_stKeyEvent[index].pfnKeyProc) {
            LOGE("This function has been registered !\n");
            return -1;
        }
    }
    
    KEY_EVENT_LOCK();
    if (index >= 0 && index < KEY_EVENT_NUM)
    {
        g_stKeyEvent[index].enKeyType = enKeyType;
        g_stKeyEvent[index].enKeyState = enKeyState;
        g_stKeyEvent[index].pfnKeyProc = pfnKeyProc;
    }
    KEY_EVENT_UNLOCK();
    
    return 0;
}


int KeyEventUnRegister(KEY_TYPE_E enKeyType, KEY_STATE_E enKeyState, KEY_PROC_CALLBACK_FN_PTR pfnKeyProc)
{
    int index = 0;

    KEY_EVENT_LOCK();
    for (index = 0; index < KEY_EVENT_NUM; index++)
    {
        if (pfnKeyProc == g_stKeyEvent[index].pfnKeyProc) 
        {
            g_stKeyEvent[index].bRun = 0;
            g_stKeyEvent[index].enKeyType = KEY_TYPE_NONE;
            g_stKeyEvent[index].enKeyState = KEY_STATE_NONE;
            g_stKeyEvent[index].pfnKeyProc = NULL;
            break;
        }
    }
    KEY_EVENT_UNLOCK();

    return 0;
}

int KeyDeinit()
{
    int index = 0;
    
    pthread_cancel(g_keyProcPid);
    
    KEY_EVENT_LOCK();
    for (index = 0; index < KEY_EVENT_NUM; index++)
    {
        g_stKeyEvent[index].bRun = 0;
        g_stKeyEvent[index].enKeyType = KEY_TYPE_NONE;
        g_stKeyEvent[index].enKeyState = KEY_STATE_NONE;
        g_stKeyEvent[index].pfnKeyProc = NULL;
    }
    KEY_EVENT_UNLOCK();

    return 0;
}

